package com.clx.chat.controller;

import com.alibaba.fastjson2.JSON;

import com.clx.chat.config.RabbitMQConfig;
import com.clx.chat.handler.NettyServerHandler;
import com.clx.chat.mapper.ContactMapper;
import com.clx.chat.mapper.MessageMapper;
import com.clx.common.domain.entity.Contact;
import com.rabbitmq.client.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.core.MessagePropertiesBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.Map;


/**
 * 消息发送者
 */
@Service
@Slf4j
public class RabbitmqSender {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private MessageMapper messageMapper;

    @Autowired
    private ContactMapper contactMapper;

    /**
     * 用户发送离线消息
     * @param temp
     */
    public void sendMessage(Map<String,String> temp) {
        // 构造消息属性
        MessageProperties props = MessagePropertiesBuilder.newInstance()
                .setDeliveryMode(MessageDeliveryMode.PERSISTENT) // 设置持久化
                .setContentType(MessageProperties.CONTENT_TYPE_JSON)
                .build();
        Integer receiverId = Integer.valueOf(temp.get("receiverId"));
        Integer senderId = Integer.valueOf(temp.get("sendId"));
        String text = temp.get("text");
        //先存储到数据库
        com.clx.common.domain.entity.Message message1= saveMessageAndContact(senderId, receiverId, text);
        String s = JSON.toJSONString(message1);
        //返回消息给发送用户
        io.netty.channel.Channel channel1 = NettyServerHandler.getChanelByUserId(senderId);
        channel1.writeAndFlush(new TextWebSocketFrame(s));
        // 发送持久化消息到队列
        rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_NAME,RabbitMQConfig.ROUTING_KEY, new Message(JSON.toJSONBytes(s), props));
    }

    /**
     * 添加联系人
     */
    public void addContact(Integer userId) {
        // 发送消息到队列
        rabbitTemplate.convertAndSend("contact-add","contact-key", userId);
    }

    /**
     * 检查用户是否有离线消息
     */
    public Message isHaveNotOnline(){
        return rabbitTemplate.receive(RabbitMQConfig.QUEUE_NAME);

    }

    /**
     * 手动确认消息
     */
    public void ackMessage(Message message)  {
        // 手动确认消息
        Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel(false);
        try {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }



    /**
     * 存储消息到数据库
     * @param senderId
     * @param receiverId
     * @param text
     * @return
     */
    @Transactional
    public com.clx.common.domain.entity.Message saveMessageAndContact(Integer senderId, Integer receiverId, String text){
        try {
            //根据recriverId查询concat表
            Contact contact = contactMapper.selectByuser(senderId, receiverId);
            Contact contact2 = contactMapper.selectByuser(receiverId, senderId);
            //同时更新两个用户联系人的lastmessage
            contact.setLastMessage(text);
            contact2.setLastMessage(text);
            contactMapper.updateContact(contact);
            contactMapper.updateContact(contact2);
            //存储message到数据库
            com.clx.common.domain.entity.Message message = com.clx.common.domain.entity.Message.builder()
                    .type(1)
                    .status(0)
                    .content(text)
                    .senderId(senderId)
                    .receiverId(receiverId)
                    .contactId(contact.getId())
                    .isRead(0)
                    .build();
            messageMapper.insertMessage(message);
            return message;
        } catch (Exception e) {
            log.error("存储聊天消息失败：",e);
            throw new RuntimeException(e);
        }
    }
}
